//动态栈
#ifndef __DYNAMICSTACK__HPP
#define __DYNAMICSTACK__HPP

#include"VirtualStack.hpp"

namespace NgSiuKei {

template<class TheClass>
struct dynamic_stack_node {
    TheClass val;
    dynamic_stack_node<TheClass> *next;
};
#define ds_node dynamic_stack_node

template<class TheClass>
class DynamicStack: public VirtualStack<TheClass> {
    public:
    DynamicStack(void);
    ~DynamicStack(void);

    public:
    //清空
    void clear(void);
    //获取栈顶元素
    TheClass getTopVal(void) const;
    //入栈
    void push(const TheClass val);
    //出栈
    TheClass pop(void);
    //打印栈
    void print(void) const;

    private:
    ds_node<TheClass> *top;
};

template<class TheClass>
DynamicStack<TheClass>::DynamicStack(void): VirtualStack<TheClass>() {
    this->top = nullptr;
}

template<class TheClass>
DynamicStack<TheClass>::~DynamicStack(void) {
    this->clear();
}

template<class TheClass>
void DynamicStack<TheClass>::clear(void) {
    this->size = 0;
    ds_node<TheClass> *currentNode;
    while(nullptr != this->top) {
        currentNode = this->top;
        this->top = this->top->next;
        delete currentNode;
    }
}

template<class TheClass>
TheClass DynamicStack<TheClass>::getTopVal(void) const {
    if(this->isEmpty()) {
        throw EXCEPTION_IS_EMPTY;
    }
    return this->top->val;
}

template<class TheClass>
void DynamicStack<TheClass>::push(const TheClass val) {
    ds_node<TheClass> *newTop = new ds_node<TheClass>();
    newTop->val = val;
    newTop->next = this->top;
    this->top = newTop;
    this->size++;
}

template<class TheClass>
TheClass DynamicStack<TheClass>::pop(void) {
    if(this->isEmpty()) {
        return 0;
    }
    ds_node<TheClass> *deleteTop = this->top;
    this->top = this->top->next;
    TheClass resultVal = deleteTop->val;
    delete deleteTop;
    this->size--;
    return resultVal;
}

template<class TheClass>
void DynamicStack<TheClass>::print(void) const {
    cout << "打印动态链：[ ";
    ds_node<TheClass> *currentNode = this->top;
    while(nullptr != currentNode) {
        cout << currentNode->val << ' ';
        currentNode = currentNode->next;
    }
    cout << ']' << endl;
}

}

#endif